/* Use ltgen */

#ifndef LTPRINT_H_
#define LTPRINT_H_

#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

#include "src/lta.h"
#include "src/ltbase.h"

static inline void
ltprint_FPrint_U32(FILE* fp, uint32_t x) {
    fprintf(fp, "%" PRIu32, x);
}

static inline void
ltprint_FPrint_U64(FILE* fp, uint64_t x) {
    fprintf(fp, "%" PRIu64, x);
}

static inline void
ltprint_FPrint_USize(FILE* fp, lt_USize x) {
    fprintf(fp, "%" lt_FmtUSize, x);
}

static inline void
ltprint_FPrint_Char(FILE* fp, char x) {
    fputc(x, fp);
}

static inline void
ltprint_FPrint_CharQuote(FILE* fp, char x) {
    putc('\'', fp);
    fputc(x, fp);
    putc('\'', fp);
}

static inline void
ltprint_FPrint_Ptr(FILE* fp, void* x) {
    fprintf(fp, "%p", x);
}

static inline void
ltprint_FPrint_String(FILE* fp, char const* x) {
    fputs(x, fp);
}

static inline void
ltprint_FPrint_StringQuote(FILE* fp, char const* x) {
    fputc('\"', fp);
    for (; *x != 0; ++x) {
        switch (*x) {
            case '\"':
                fputc('\\', fp);
                fputc('\"', fp);
                break;
            case '\t':
                fputc('\\', fp);
                fputc('t', fp);
                break;
            case '\n':
                fputc('\\', fp);
                fputc('n', fp);
                break;
            case '\r':
                fputc('\\', fp);
                fputc('r', fp);
                break;
            default: fputc(*x, fp); break;
        }
    }
    fputc('\"', fp);
}

lt_ForceInline void
ltprint_FPrint_LtaU32(FILE* fp, lta_U32Arr const* x) {
    ltprint_FPrint_String(fp, "[");

    bool first = true;
    lta_ForEach(i, *x) {
        if (first) {
            first = false;
        } else {
            ltprint_FPrint_String(fp, ", ");
        }
        ltprint_FPrint_U32(fp, x->data[i]);
    }

    ltprint_FPrint_String(fp, "]");
}

lt_ForceInline void
ltprint_FPrint_LtaStrings(FILE* fp, lta_Strings const* strings) {
    ltprint_FPrint_String(fp, "[");

    bool first = true;
    lta_ForEach(i, *strings) {
        if (first) {
            first = false;
        } else {
            ltprint_FPrint_String(fp, ", ");
        }
        ltprint_FPrint_StringQuote(fp, strings->data[i]);
    }

    ltprint_FPrint_String(fp, "]");
}

/* ltgen ltprint_Print_EPrint */
lt_ForceInline void
ltprint_Print_U32(lt_U32 x) {
    ltprint_FPrint_U32(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_U32(lt_U32 x) {
    ltprint_FPrint_U32(stderr, x);
}

lt_ForceInline void
ltprint_Print_U64(lt_U64 x) {
    ltprint_FPrint_U64(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_U64(lt_U64 x) {
    ltprint_FPrint_U64(stderr, x);
}

lt_ForceInline void
ltprint_Print_USize(lt_USize x) {
    ltprint_FPrint_USize(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_USize(lt_USize x) {
    ltprint_FPrint_USize(stderr, x);
}

lt_ForceInline void
ltprint_Print_Char(char x) {
    ltprint_FPrint_Char(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_Char(char x) {
    ltprint_FPrint_Char(stderr, x);
}

lt_ForceInline void
ltprint_Print_CharQuote(char x) {
    ltprint_FPrint_CharQuote(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_CharQuote(char x) {
    ltprint_FPrint_CharQuote(stderr, x);
}

lt_ForceInline void
ltprint_Print_Ptr(void* x) {
    ltprint_FPrint_Ptr(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_Ptr(void* x) {
    ltprint_FPrint_Ptr(stderr, x);
}

lt_ForceInline void
ltprint_Print_String(char const* x) {
    ltprint_FPrint_String(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_String(char const* x) {
    ltprint_FPrint_String(stderr, x);
}

lt_ForceInline void
ltprint_Print_StringQuote(char const* x) {
    ltprint_FPrint_StringQuote(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_StringQuote(char const* x) {
    ltprint_FPrint_StringQuote(stderr, x);
}

lt_ForceInline void
ltprint_Print_LtaU32(lta_U32Arr const* x) {
    ltprint_FPrint_LtaU32(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_LtaU32(lta_U32Arr const* x) {
    ltprint_FPrint_LtaU32(stderr, x);
}

lt_ForceInline void
ltprint_Print_LtaStrings(lta_Strings const* x) {
    ltprint_FPrint_LtaStrings(stdout, x);
}

lt_ForceInline void
ltprint_EPrint_LtaStrings(lta_Strings const* x) {
    ltprint_FPrint_LtaStrings(stderr, x);
}

/* ltgen_End */

#endif
